package com.cruise.common.mybatis.util;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.cglib.beans.BeanCopier;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ：Cruise
 * @version ：1.0
 * @Calss ：CommonBeanUtil
 * @Description ：TODO
 * @date ：2021/4/18 下午7:24
 **/
public class CommonBeanUtil {

    /**
     * BeanCopier的缓存
     */
    static final ConcurrentHashMap<String, BeanCopier> BEAN_COPIER_CACHE = new ConcurrentHashMap<>();
    /**
     * Page<Entity> 分页对象转 Page<Vo>
     *
     * @param page
     * @param v
     * @return com.baomidou.mybatisplus.core.metadata.IPage<V>
     * @author ws
     * @mail 1720696548@qq.com
     * @date 2020/4/23 0023 11:26
     */
    public static <T, V> IPage<V> pageVo(Page<T> page, Class<V> v) {
        if (page == null) {
            return null;
        }
        return page.convert(item -> convert(item, v));
    }

    /**
     * dot ,do ,entity 相互转换（使用cglib）
     * <P>
     *  1、使用 cglib, 几乎无性能损耗, 和 mapstruct 和 get/set 性能不相上下,甚至更快
     *   ---- mapstruct 在 编译时生成class文件的set,get方法，功能更全，支持属性key不一致，属性类型不一致的配置替换
     *   ---- cglib 在 BeanCopier.create动态生成set/get方法,功能单一，但性能可观,注意避免频繁 BeanCopier.create, 会重复动态生成get/set,将达不到预期的性能效果
     *
     *  2、使用 springboot的
     *   ---- BeanUtils.copyProperties(oldClass, newInstance);
     *
     *  3、使用 mapstruct
     *   ---- 参考 AdminAuthorityConverter 转换类,启动项目会动态生成 AdminAuthorityConverterImpl的calss类，并生成转换方法
     * </P>
     *
     * @param oldClass 原数据--Dto，Vo，entity
     * @param newClass 转换为--Dto，Vo，entity
     * @return
     */
    public static <E> E convert(Object oldClass, Class<E> newClass) {
        if (oldClass == null) {
            return null;
        }
        if (newClass == null) {
            return null;
        }
        E newInstance = null;
        try {
            newInstance = newClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        String key = oldClass.getClass().getName() + ":" + newClass.getName();
        BeanCopier copier = null;
        if (BEAN_COPIER_CACHE.containsKey(key)) {
            copier = BEAN_COPIER_CACHE.get(key);
        } else {
            copier = BeanCopier.create(oldClass.getClass(), newInstance.getClass(), false);
            BEAN_COPIER_CACHE.put(key, copier);
        }
        copier.copy(oldClass, newInstance, null);
        return newInstance;
    }
}
